import * as THREE from 'three';
import { BufferGeometry, Color, Geometry, Material, Texture } from 'three';
import BaseThreeApp from '../BaseThreeApp';
import DebugInfo from '../DebugInfo';
import { VTKLoader } from 'three/examples/jsm/loaders/VTKLoader';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls';

class _7_1Model extends BaseThreeApp {
  public scene: THREE.Scene;
  public camera: THREE.Camera;
  public renderer: THREE.WebGLRenderer;
  public controler: TrackballControls;
  public geos: (Geometry | BufferGeometry)[] = [];
  public mats: Material[] = [];
  public texs: Texture[] = [];

  start() {
    this.scene = new THREE.Scene();
    this.camera = new THREE.PerspectiveCamera(
      60,
      this.clientWidth / this.clientHeight,
      0.1,
      1000
    );
    this.camera.position.z = 5;

    this.renderer = new THREE.WebGLRenderer({
      canvas: this.element,
    });

    this.controler = new TrackballControls(this.camera, this.element);
    this.controler.rotateSpeed = 10;
    this.controler.panSpeed = 0.5;

    const material = new THREE.MeshLambertMaterial({
      color: 0xffffff,
      side: THREE.DoubleSide,
    });
    this.mats.push(material);

    const loader = new VTKLoader();
    loader.load('models/bunny.vtk', (geo) => {
      this.geos.push(geo);
      geo.computeVertexNormals();
      geo.center();
      const mesh = new THREE.Mesh(geo, material);
      mesh.scale.set(10, 10, 10);
      this.scene.add(mesh);
    });

    const tex = new THREE.TextureLoader().load('images/bg.jpg');
    this.texs.push(tex);
    const objLoader = new OBJLoader();
    objLoader.load('models/head.obj', (group) => {
      group.traverse((o) => {
        if (o instanceof THREE.Mesh) {
          this.geos.push(o.geometry);
          if ((o.material as any).map !== undefined) {
            (o.material as any).map = tex;
          }
        }
      });
      group.scale.set(0.1, 0.1, 0.1);
      group.position.z = -20;
      this.scene.add(group);
    });

    this.renderer.setDrawingBufferSize(this.clientWidth, this.clientHeight, 1);

    const ambient = new THREE.AmbientLight(0xffffff, 0.2);
    this.scene.add(ambient);

    const light = new THREE.DirectionalLight(0xffffff, 0.7);
    light.position.set(0, 0, 10);
    this.scene.add(light);

    this.isRunning = true;
    const animate = (time) => {
      if (!this.isRunning || this.element === null) {
        return;
      }
      DebugInfo.Instance.begin();
      this.renderer.render(this.scene, this.camera);
      this.controler.update();
      DebugInfo.Instance.end();
      requestAnimationFrame(animate);
    };
    animate(0);
  }

  onresize(e: UIEvent) {
    super.onresize(e);
    console.log('onresive');
    if (this.renderer) {
      this.renderer.setDrawingBufferSize(
        this.clientWidth,
        this.clientHeight,
        1
      );
      if (this.camera && this.camera instanceof THREE.PerspectiveCamera) {
        this.camera.aspect = this.clientWidth / this.clientHeight;
        this.camera.updateProjectionMatrix();
      }
    }
    if (this.controler) {
      this.controler.handleResize();
    }
  }

  destory() {
    this.geos.forEach((v) => v.dispose());
    this.geos = [];
    this.mats.forEach((v) => v.dispose());
    this.mats = [];
    this.texs.forEach((v) => v.dispose());
    this.texs = [];
    super.destory();
  }
}

export default new _7_1Model();
